import unittest
from functionBinding import functionBinding
from functionDef import functionDef
from application import application
from Return import Return
from builtin import *
from varRef import varRef
from jsobject import *
from interpreter import interpreter
from endvals import *
from objectOps import *
from sequence import *
from conditionals import *
from sequence import *
from varBinding import *
from varMut import *
from customExceptions import *


class TestBuiltin(unittest.TestCase):
	def testPlus(self):
		p = Return(application("+",[integer(1),integer(1)]))
		i = interpreter(p)# need a program
		
		assert i.execute() == 2, '1+1 does not equal 2?'

#--	------------------------------------------------------------------

	def testMinusPlus(self):
		p = Return(application("-",[flp(3.0),application("+",[integer(1),flp(1.0)])]))
		i = interpreter(p)# need a program

		assert i.execute() == 1.0, '3-(1+1) does not equal 1.0?'

#--	------------------------------------------------------------------

	def testTimesDiv(self):
		p = Return(application("*",[integer(3),application("/",[integer(2),integer(1)])]))
		i = interpreter(p)# need a program

		assert i.execute() == 6, '3*(2/1) does not equal 6?'

#--	------------------------------------------------------------------

	def testLessThan(self):
		p = Return(application("<",[integer(3),integer(1)]))
		i = interpreter(p)# need a program

		assert i.execute() == False, '3 < 1 is False'

#--	------------------------------------------------------------------
		
	def testGreatThan(self):
		p = Return(application(">",[integer(3),integer(1)]))
		i = interpreter(p)# need a program

		assert i.execute() == True, '3 > 1 is True'

#--	------------------------------------------------------------------

	def testLessEq(self):
		p = Return(application("<=",[integer(2),integer(2)]))
		i = interpreter(p)# need a program

		assert i.execute() == True, '2 <= (3 <= 3) is True'

#--	------------------------------------------------------------------

	def testGreatThan(self):
		p = Return(application(">=",[integer(4),integer(3)]))
		i = interpreter(p)# need a program

		assert i.execute() == True, '4 >= (3 >= 3) is True'

#--	------------------------------------------------------------------

	def testAnd_(self):
		p = Return(application("and",[boolean(True),boolean(True)]))
		i = interpreter(p)# need a program

		assert i.execute() == True, 'True and True is True'

#--	------------------------------------------------------------------

	def testAnd_(self):
		p = Return(application("and",[boolean(False),boolean(True)]))
		i = interpreter(p)# need a program

		assert i.execute() == False, 'False and True is False'

#--	------------------------------------------------------------------

	def testOr_(self):
		p = Return(application("or",[boolean(True),boolean(True)]))
		i = interpreter(p)# need a program

		assert i.execute() == True, 'True or True is True'

#--	------------------------------------------------------------------

	def testOr_(self):
		p = Return(application("or",[boolean(True),boolean(False)]))
		i = interpreter(p)# need a program

		assert i.execute() == True, 'True or False is True'

#--	------------------------------------------------------------------

	def testNot_(self):
		p = Return(application("not",[boolean(True)]))
		i = interpreter(p)# need a program

		assert i.execute() == False, 'not True is False'

#--	------------------------------------------------------------------

	def testStringLength(self):
		p = Return(application("string-length",[stringval("thecar")]))
		i = interpreter(p)# need a program

		assert i.execute() == 6, '6 is the length of \"thecar\"'

#--	------------------------------------------------------------------

	def testSubString(self):
		p = Return(application("substring",[stringval("thecar"),integer(1),integer(4)]))
		i = interpreter(p)# need a program

		assert i.execute().__str__() == "hec", 'hec is the substring(1,4) of \"thecar\"'

#--	------------------------------------------------------------------

	def testStringEquals(self):
		p = Return(application("string=?",[stringval("thecar"),stringval("thecar")]))
		i = interpreter(p)# need a program

		assert i.execute() == True, '\"thecar\" == \"thecar\"'

#--	------------------------------------------------------------------

	def testStringLessThan(self):
		p = Return(application("string<?",[stringval("ahecar"),stringval("thecar")]))
		i = interpreter(p)# need a program

		assert i.execute() == True, '\"ahecar\" < \"thecar\" is True'

#--	------------------------------------------------------------------

	def testEquals(self):
		p = Return(application("==",[stringval("thecar"),stringval("thecar")]))
		i = interpreter(p)# need a program

		assert i.execute() == False, 'object \"thecar\" == object \"thecar\" is False'

#--	------------------------------------------------------------------


	def testIntQ(self):
		p = Return(application("integer?",[integer(1)]))
		i = interpreter(p)# need a program
		assert i.execute() == True, 'int 1 is an int'
		p = Return(application("integer?",[flp(1.0)]))
		i = interpreter(p)# need a program
		assert i.execute() == False, 'Float 1.0 is not an int'

#--	------------------------------------------------------------------

	def testBoolQ(self):
		p = Return(application("boolean?",[boolean(True)]))
		i = interpreter(p)# need a program
		assert i.execute() == True, 'True is an int'
		p = Return(application("boolean?",[flp(1.0)]))
		i = interpreter(p)# need a program
		assert i.execute() == False, '1.0 is not a bool'

#--	------------------------------------------------------------------

	def testFloatQ(self):
		p = Return(application("floating-point?",[flp(1.0)]))
		i = interpreter(p)# need a program
		assert i.execute() == True, 'Float 1.0 is an float'
		p = Return(application("floating-point?",[integer(1)]))
		i = interpreter(p)# need a program
		assert i.execute() == False, '1 is not a Float'

#--	------------------------------------------------------------------

	def testVoidQ(self):
		p = Return(application("void?",[void()]))
		i = interpreter(p)# need a program
		assert i.execute() == True, 'void is void'
		p = Return(application("void?",[flp(1.0)]))
		i = interpreter(p)# need a program
		assert i.execute() == False, 'void is not a float'

#--	------------------------------------------------------------------

	def testStringQ(self):
		p = Return(application("string?",[stringval("g")]))
		i = interpreter(p)# need a program
		assert i.execute() == True, '\"g\" is String'
		p = Return(application("string?",[flp(1.0)]))
		i = interpreter(p)# need a program
		assert i.execute() == False, '\"g\" is not a float'

#--	------------------------------------------------------------------

	def testInstanceof(self):
		p = functionBinding( [functionDef("test", [], Return(integer(0)) ) ],
													varBinding("testObject", new(varRef("test"),[]),
																			ifthen(application("instanceof", [varRef("testObject"), varRef("test")]),
																						Return(integer(1)),
																						Return(integer(0))
																						)
																 		 )
												 )
		i = interpreter(p)	
		assert i.execute() == 1, "testInstanceof Failed! Part 1"
		p = Return(application("instanceof",[flp(1.0),flp(1.0)]))
		i = interpreter(p)
		assert i.execute() == False, 'float is not a class'

#--	------------------------------------------------------------------

	def testClosureQ(self):
		p = functionBinding([functionDef("h",[], None)], Return(application("closure?", [varRef("h")] ) ) )
		i = interpreter(p)
		assert i.execute() == False, 'is a closure'
		p = Return(application("closure?",[flp(1.0)]))
		i = interpreter(p)
		assert i.execute() == False, 'is a closure'

#--	------------------------------------------------------------------

	def testPlainQ(self):
		p = Return(application("plain?",[jsobject()]))
		i = interpreter(p)# need a program
		assert i.execute() == True, 'object is plain'
		p = Return(application("plain?",[stringval("g")]))
		i = interpreter(p)# need a program
		assert i.execute() == False, 'not a stringval'

#--	------------------------------------------------------------------

	def testPrint(self):
		print "\n-------------------------------------------------------"
		print "There should be two copies of the line below this one"
		print "If you see this, this test suceeded"
		p = application("print",[stringval("If you see this, this test suceeded")])
		i = interpreter(p)
		i.execute()
		assert True, "\nRead the above text"

#--	------------------------------------------------------------------

	def testRead(self):
		print "\n-------------------------------------------------------"
		print "What you write should appear below:"
		print "Write Something: ",
		p = application("print",[application("read-line",[])])
		i = interpreter(p)
		i.execute()
		assert True, "\nRead the above text"


if __name__ == '__main__':
    unittest.main()


